package com.app.camera;

import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.ErrorCallback;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.FrameLayout.LayoutParams;
import droid.frame.ui.dialog.AppDialog;

/**
 * 拍照预览
 * 
 * @author coffee <br>
 *         2015-12-29下午6:33:01
 */
public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
	private Camera mCamera;
	// private Context context;
	// 当前Camera状态：预览|非预览
	private boolean isPreview = false;
	private List<Size> mSupportedPreviewSizes;
	private Size mPreviewSize;

	public CameraSurfaceView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.getHolder().addCallback(this);
	}

	private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
		if (sizes == null) {
			return null;
		}
		final double ASPECT_TOLERANCE = 0.1;
		double targetRatio = (double) w / h;
		Size optimalSize = null;
		// Try to find an size match aspect ratio and size
		for (Size size : sizes) {
			double ratio = (double) size.width / size.height;
			if (Math.abs(ratio - targetRatio) < ASPECT_TOLERANCE) {
				optimalSize = size;
			}
		}
		// Cannot find the one match the aspect ratio, ignore the requirement
		// 找到宽高比最接近targetRatio这个的
		if (optimalSize == null) {
			double min = Integer.MAX_VALUE;
			for (Size size : sizes) {
				double tmp = (double) size.height / size.width;
				if (Math.abs(tmp - targetRatio) < min) {
					min = Math.abs(tmp - targetRatio);
					optimalSize = size;
				}
			}
		}
		return optimalSize;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec));
		// int viewWidth = getMeasuredWidth();
		// int viewHeight = viewWidth;
		//
		// // Log.d("image:scale", imageWidth + "," + imageHeight + " -- " + viewWidth + "," + viewHeight);
		// widthMeasureSpec = MeasureSpec.makeMeasureSpec(viewWidth, MeasureSpec.EXACTLY);
		// // 精确计算高度
		// heightMeasureSpec = MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.EXACTLY);
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}

	/**
	 * 当开始拍照时，会依次调用shutter的onShutter()方法 raw的onPictureTaken方法,jpeg的onPictureTaken方法.<br>
	 * 三个参数的作用是shutter--拍照瞬间调用，raw--获得没有压缩过的图片数据，jpeg---返回jpeg的图片数据 当你不需要对照片进行处理，可以直接用null代替.
	 */
	// public void takePicture() {
	// //this.mCamera.takePicture(null, null, jpeg);
	// }

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		try {
			Display display = ((Activity) getContext()).getWindowManager().getDefaultDisplay();
			DisplayMetrics dm = new DisplayMetrics();
			display.getMetrics(dm);
			int width = dm.widthPixels - (int) (16 * dm.density);
			LayoutParams params = new LayoutParams(width, width);
			params.leftMargin = (int) (16 * dm.density);
			params.topMargin = (int) (60 * dm.density);
			params.rightMargin = (int) (16 * dm.density);
			setLayoutParams(params);
			// 默认后置
			int cameraId = 0;
			CameraInfo cameraInfo = new CameraInfo();
			for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
				Camera.getCameraInfo(i, cameraInfo);
				if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
					cameraId = i;
					break;
				}
			}
			mCamera = Camera.open(cameraId);
			// mCamera = null;
			if (mCamera == null) {
				return;
			}
			// 设置旋转角度
			mCamera.setDisplayOrientation(90);

			Camera.CameraInfo info = new Camera.CameraInfo();
			Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);
			int rotation = ((Activity) getContext()).getWindowManager().getDefaultDisplay().getRotation();
			int degrees = 0;
			switch (rotation) {
			case Surface.ROTATION_0:
				degrees = 0;
				break; // Natural orientation
			case Surface.ROTATION_90:
				degrees = 90;
				break; // Landscape left
			case Surface.ROTATION_180:
				degrees = 180;
				break;// Upside down
			case Surface.ROTATION_270:
				degrees = 270;
				break;// Landscape right
			}
			int rotate = (info.orientation - degrees + 360) % 360;

			Parameters parameters = mCamera.getParameters();
			parameters.setJpegQuality(100);//图片质量
			parameters.setPictureFormat(ImageFormat.JPEG);// 设置拍照后存储的图片格式
			parameters.setRotation(rotate);

			// List<String> focusModes = mParams.getSupportedFocusModes();
			parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
			// 闪光灯自动模式
			parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
			// 设置窗口大小
			mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();
			if (mSupportedPreviewSizes != null) {
				mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, width);
			}
			// mParams.setPictureSize(size.width, size.height);
			parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
			mCamera.setParameters(parameters);

			// 设置预览面板
			mCamera.setPreviewDisplay(holder);
			// 设置ErrorCallback
			mCamera.setErrorCallback(new ErrorCallback() {
				@Override
				public void onError(int error, Camera camera) {
					mCamera.release();
				}
			});
			mCamera.setPreviewCallback(previewCallback);
			// 开启预览
			mCamera.startPreview();
			isPreview = true;
		} catch (Exception e) {
			Log.e("camera_surfaceview", e.getMessage());
		}
	}

	// public void onOrientationChanged(int orientation) {
	// if (orientation == ORIENTATION_UNKNOWN) return;
	// android.hardware.Camera.CameraInfo info =
	// new android.hardware.Camera.CameraInfo();
	// android.hardware.Camera.getCameraInfo(cameraId, info);
	// orientation = (orientation + 45) / 90 * 90;
	// int rotation = 0;
	// if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
	// rotation = (info.orientation - orientation + 360) % 360;
	// } else { // back-facing camera
	// rotation = (info.orientation + orientation) % 360;
	// }
	// mParameters.setRotation(rotation);
	// }

	private AppDialog dialog;

	/**
	 * This is called immediately after any structural changes (format or size) have been made to the surface.
	 */
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		// 程序第一次启动的时候，调用该方法
		isPreview = true;
		if (mCamera == null) {
			if (getContext() instanceof Activity) {
				if (dialog != null && dialog.isShowing()) {
					return;
				}
				final Activity activity = (Activity) getContext();
				AppDialog dialog = new AppDialog(activity);
				dialog.setContent("设备出现错误, 请检查相机权限设置或重新启动");
				dialog.setConfirmClickListener("我知道了", null);
				dialog.show();
				//
				dialog.setOnDismissListener(new OnDismissListener() {
					@Override
					public void onDismiss(DialogInterface dialog) {
						activity.finish();
					}
				});
			}
		} else {
			// mCamera.startPreview();
		}
	}

	private byte[] previewData;

	Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {
		@Override
		public void onPreviewFrame(byte[] data, Camera camera) {
			previewData = data;
		}
	};

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		// java.lang.RuntimeException: Camera is being used after Camera.release() was called
		if (mCamera != null) {
			mCamera.setPreviewCallback(null);// 一定要设置为null, 否则报上述异常
			mCamera.stopPreview();// 停止预览
			mCamera.release(); // 释放资源
			mCamera = null;
		}
	}

	public boolean isPreview() {
		return this.isPreview;
	}

	public Camera getCamera() {
		return this.mCamera;
	}

	public byte[] getPreviewData() {
		return this.previewData;
	}

	// private void updateCameraParameters() {
	// if (mCamera != null) {
	// Camera.Parameters p = mCamera.getParameters();
	//
	// long time = new Date().getTime();
	// p.setGpsTimestamp(time);
	//
	// Size pictureSize = findBestPictureSize(p);
	// p.setPictureSize(pictureSize.width, pictureSize.height);
	//
	// // Set the preview frame aspect ratio according to the picture size.
	// Size size = p.getPictureSize();
	// Display display = ((Activity) getContext()).getWindowManager().getDefaultDisplay();
	// DisplayMetrics dm = new DisplayMetrics();
	// display.getMetrics(dm);
	// LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, dm.widthPixels);
	// params.leftMargin = (int) (16 * dm.density);
	// params.topMargin = (int) (60 * dm.density);
	// params.rightMargin = (int) (16 * dm.density);
	// setLayoutParams(params);
	//
	// // frameLayout.setAspectRatio((double) size.width / size.height);
	//
	// Size previewSize = findBestPreviewSize(p);
	// p.setPreviewSize(previewSize.width, previewSize.height);
	//
	// mCamera.setParameters(p);
	//
	// int supportPreviewWidth = previewSize.width;
	// int supportPreviewHeight = previewSize.height;
	//
	// int srcWidth = getScreenWH().widthPixels;
	// int srcHeight = getScreenWH().heightPixels;
	//
	// int width = Math.min(srcWidth, srcHeight);
	// int height = width * supportPreviewWidth / supportPreviewHeight;
	//
	// }
	// }
	//
	// private Size findBestPictureSize(Camera.Parameters parameters) {
	// int diff = Integer.MIN_VALUE;
	// String pictureSizeValueString = parameters.get("picture-size-values");
	//
	// // saw this on Xperia
	// if (pictureSizeValueString == null) {
	// pictureSizeValueString = parameters.get("picture-size-value");
	// }
	//
	// if (pictureSizeValueString == null) {
	// return mCamera.new Size(getScreenWH().widthPixels, getScreenWH().heightPixels);
	// }
	//
	// Log.d("tag", "pictureSizeValueString : " + pictureSizeValueString);
	// int bestX = 0;
	// int bestY = 0;
	//
	// for (String pictureSizeString : COMMA_PATTERN.split(pictureSizeValueString)) {
	// pictureSizeString = pictureSizeString.trim();
	//
	// int dimPosition = pictureSizeString.indexOf('x');
	// if (dimPosition == -1) {
	// Log.e("camera_surfaceView", "Bad pictureSizeString:" + pictureSizeString);
	// continue;
	// }
	//
	// int newX = 0;
	// int newY = 0;
	//
	// try {
	// newX = Integer.parseInt(pictureSizeString.substring(0, dimPosition));
	// newY = Integer.parseInt(pictureSizeString.substring(dimPosition + 1));
	// } catch (NumberFormatException e) {
	// Log.e("camera_surfaceView", "Bad pictureSizeString:" + pictureSizeString);
	// continue;
	// }
	//
	// Point screenResolution = new Point(getScreenWH().widthPixels, getScreenWH().heightPixels);
	//
	// int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
	// if (newDiff == diff) {
	// bestX = newX;
	// bestY = newY;
	// break;
	// } else if (newDiff > diff) {
	// if ((3 * newX) == (4 * newY)) {
	// bestX = newX;
	// bestY = newY;
	// diff = newDiff;
	// }
	// }
	// }
	//
	// if (bestX > 0 && bestY > 0) {
	// return mCamera.new Size(bestX, bestY);
	// }
	// return null;
	// }
	//
	// private Size findBestPreviewSize(Camera.Parameters parameters) {
	//
	// String previewSizeValueString = null;
	// int diff = Integer.MAX_VALUE;
	// previewSizeValueString = parameters.get("preview-size-values");
	//
	// if (previewSizeValueString == null) {
	// previewSizeValueString = parameters.get("preview-size-value");
	// }
	//
	// if (previewSizeValueString == null) { // 有些手机例如m9获取不到支持的预览大小 就直接返回屏幕大小
	// return mCamera.new Size(getScreenWH().widthPixels, getScreenWH().heightPixels);
	// }
	// Log.d("tag", "previewSizeValueString : " + previewSizeValueString);
	// int bestX = 0;
	// int bestY = 0;
	//
	// for (String prewsizeString : COMMA_PATTERN.split(previewSizeValueString)) {
	// prewsizeString = prewsizeString.trim();
	//
	// int dimPosition = prewsizeString.indexOf('x');
	// if (dimPosition == -1) {
	// Log.e("camera_surfaceView", "Bad prewsizeString:" + prewsizeString);
	// continue;
	// }
	//
	// int newX = 0;
	// int newY = 0;
	//
	// try {
	// newX = Integer.parseInt(prewsizeString.substring(0, dimPosition));
	// newY = Integer.parseInt(prewsizeString.substring(dimPosition + 1));
	// } catch (NumberFormatException e) {
	// Log.e("camera_surfaceView", "Bad prewsizeString:" + prewsizeString);
	// continue;
	// }
	//
	// Point screenResolution = new Point(getScreenWH().widthPixels, getScreenWH().heightPixels);
	//
	// int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
	//
	// if (newDiff == diff) {
	// bestX = newX;
	// bestY = newY;
	// break;
	// } else if (newDiff < diff) {
	// if ((3 * newX) == (4 * newY)) {
	// bestX = newX;
	// bestY = newY;
	// diff = newDiff;
	// }
	// }
	// }
	// if (bestX > 0 && bestY > 0) {
	// return mCamera.new Size(bestX, bestY);
	// }
	// return null;
	// }
	//
	// protected DisplayMetrics getScreenWH() {
	// DisplayMetrics dMetrics = new DisplayMetrics();
	// dMetrics = this.getResources().getDisplayMetrics();
	// return dMetrics;
	// }
}
